import json
import re
from datetime import datetime

from flask import request, current_app, make_response, jsonify, session
from . import passport_blue
from ... import redis_store, constants, models, db
from ...utils.captcha.captcha import captcha
from ...utils.response_code import RET
from ...utils.send_messge.alyun_send_message import Send_SMS


@passport_blue.route('/image_code')
def image_code():
    try:
        # 1. 获取前端传递过来的参数
        cur_id = request.args.get('cur_id')
        pre_id = request.args.get('pre_id')

        # 2. 调用captcha工具获取图片验证码，验证码的值，验证码图片(二进制)
        code_name, code_text, code_image = captcha.generate_captcha()

        # 3. 将图片验证码的值保存到redis中
        try:
            # 参数1：key,参数2：value,参数3：有效期
            redis_store.set("image_code:{}".format(cur_id), code_text, constants.IMAGE_CODE_REDIS_EXPIRES)

            # 4. 判断是否有上一次的图片验证码
            if pre_id:
                redis_store.delete('image_code:{}'.format(pre_id))
        except Exception as e:
            current_app.logger.error(e)
            return '图片验证码获取失败！'
    except Exception as e:
        print(e)
        return jsonify(errno=RET.UNKOWNERR, errmsg='未知错误')
    # 返回图片
    response = make_response(code_image)
    response.headers['Content-Type'] = 'image/png'
    return response


@passport_blue.route('/sms_code', methods=['POST'])
def sms_code():
    try:
        # 1. 获取参数
        dict_data = json.loads(request.data)
        mobile = dict_data.get('mobile')
        image_code = dict_data.get('image_code')
        image_code_id = dict_data.get('image_code_id')

        # 2. 参数为空的校验
        if not all(['mobile', 'image_code', 'image_code_id']):
            return jsonify(errno=RET.PARAMERR, errmsg='参数不全！')
        # 3. 校验参数，手机号码格式
        if not re.match(r'^(13[0-9]|14[5|7]|15[0|1|2|3|5|6|7|8|9]|18[0|1|2|3|5|6|7|8|9])\d{8}$', mobile):
            return jsonify(errno=RET.DATAERR, errmsg="手机号码格式错误！")

        # 4. 通过图片验证码编号获取图片验证码
        try:
            redis_image_code = redis_store.get('image_code:%s' % image_code_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DATAERR, errmsg="操作redis失败！")

        # 5. 判断图片验证码是否过期
        if not redis_image_code:
            return jsonify(errno=RET.NODATA, errmsg="图片验证码已过期！")

        # 6. 判断图片验证码是否正确
        if image_code.upper() != redis_image_code.upper():
            return jsonify(errno=RET.DATAERR, errmsg="图片验证码错误！")

        # 7. 删除图片验证码
        try:
            redis_store.delete('image_code:%s' % image_code_id)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DATAERR, errmsg="删除图片验证码失败！")

        # 8. 生成一个随机的短信验证码并发送短信
        random_code = Send_SMS().get_random_code()  # 随机生成的code
        res_info = Send_SMS().send(mobile, random_code)
        if res_info['code'] != 'OK':
            return jsonify(errno=10000, errmsg="短信发送失败！")

        # 9. 将短信验证码存入redis中
        try:
            redis_store.set('sms_code:{}'.format(mobile), random_code, constants.SMS_CODE_REDIS_EXPIRES)
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DATAERR, errmsg="短信验证码存入redis中失败！")
    except Exception as e:
        print(e)
        return jsonify(errno=RET.UNKOWNERR, errmsg='未知错误')
    # 10. 返回正确的响应
    return jsonify(errno=RET.OK, errmsg="短信发送成功！")


# 注册接口
@passport_blue.route('/register', methods=['POST'])
def register():
    try:
        # 1, 获取参数
        # data_dict = json.loads(json_data)
        data_dict = request.json  # 这一句和上面的方法是一致的，这个更简洁
        mobile = data_dict.get('mobile')
        sms_code = data_dict.get('sms_code')
        password = data_dict.get('password')
        # 2, 校验参数，为空校验
        if not all([mobile, sms_code, password]):
            return jsonify(errno=RET.DATAERR, errmsg='参数不能为空')
        # 3, 手机号作为key取出redis中的短信验证码
        try:
            redis_sms_code = redis_store.get('sms_code:{}'.format(mobile))
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='在redis中提取短信验证码失败！')
        # 4, 判断短信验证码是否过期
        if not redis_sms_code:
            return jsonify(errno=RET.DATAERR, errmsg='短信验证码过期!')
        # 5, 判断短信验证码是否正确
        if sms_code != redis_sms_code:
            return jsonify(errno=RET.DATAERR, errmsg='短信验证码错误!')
        # 6, 删除短信验证码
        try:
            redis_store.delete('sms_code:{}'.format(mobile))
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='在redis中删除短信验证码失败！')
        # 7, 创建用户对象
        uer_obj = models.User()
        # 8, 设置用户对象属性
        uer_obj.nick_name = mobile
        uer_obj.mobile = mobile
        # 这里调用了User类的属性方法进行加密
        uer_obj.password = password
        uer_obj.signature = '改用户很懒，什么都没有写'
        # 9, 保存用户到数据库
        try:
            db.session.add(uer_obj)
            db.session.commit()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='用户存储到数据库失败！')
    except Exception as e:
        return jsonify(errno=RET.UNKOWNERR, errmsg='未知错误')
    # 10, 返回响应
    return jsonify(errno=RET.OK, errmsg='注册成功！', data=uer_obj.to_dict())


# 登录接口
@passport_blue.route('/login', methods=['POST'])
def login():
    try:
        # 1. 获取数据
        mobile = request.json.get('mobile')
        password = request.json.get('password')
        # 2. 校验参数是否为空
        if not all([mobile, password]):
            return jsonify(errno=RET.DATAERR, errmsg='参数不全')
        # 3. 根据手机号码从数据库中获取用户
        try:
            user = models.User.query.filter(models.User.mobile == mobile).first()
        except Exception as e:
            current_app.logger.error(e)
            return jsonify(errno=RET.DBERR, errmsg='获取用户失败！')
        # 4. 判断用户是否存在
        if not user:
            return jsonify(errno=RET.DATAERR, errmsg='该用户不存在！')
        # 5. 判断密码是否正确
        if not user.check_password(password=password):
            return jsonify(errno=RET.DATAERR, errmsg='密码错误！')
        # 6. 将用户信息存入sessions中
        session['user_id'] = user.id

        # 7. 记录用户最后一次的登录时间
        user.last_login = datetime.now()
        db.session.commit()
    except Exception as e:
        return jsonify(errno=RET.UNKOWNERR, errmsg='未知错误')
    # 7. 返回结果
    return jsonify(errno=RET.OK, errmsg='登录成功！')


@passport_blue.route('/logout', methods=['POST'])
def logout():
    # 1. 删除session
    session.pop('user_id', None)
    session.pop('is_admin', None)
    # 2. 返回响应结果
    return jsonify(errno=RET.OK, errmsg='退出登录！')
